package com.freestyle.common.spring.support;

import com.freestyle.common.protocols.ModifyDataException;
import com.freestyle.common.utils.Util;
import com.jeesite.common.mybatis.annotation.Column;
import com.jeesite.common.mybatis.annotation.Table;
import com.jeesite.modules.gen.entity.GenTable;
import com.jeesite.modules.gen.service.GenTableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/***
 * 数据库异常转换
 */
@Configuration
public class DatabaseExceptionConverter {
  @Autowired
  private GenTableService genTableService;
  private Exception convertException(String pvsPrefix,Exception e){
    String lvsErrMsg[]=e.getMessage().split("### ");
    String lvsTmp=lvsErrMsg[1];
    if (lvsTmp.contains("详细：")){
      lvsTmp=lvsTmp.split("详细：")[1];
    }
    else{
      lvsTmp=lvsTmp.split("DETAIL: ")[1];
    }

    String lvFields[]=null;
    String lvsValues=lvsTmp.contains("键值")? lvsTmp.split("=")[1]:"";
    if (lvsTmp.contains("键值")) {
      String regex = "(?<=\\()(.+?)(?=\\))";
      Pattern p = Pattern.compile(regex);
      Matcher lvMatcher = p.matcher(lvsTmp);
      lvsTmp = null;
      if (lvMatcher.find()) {
        lvsTmp = lvMatcher.group(0);
      }
      if (lvsTmp == null) return e;
      lvFields = lvsTmp.split(","); //获得Fields
    }
    else if (lvsErrMsg[1].contains("非空约束")){
      String regex = "\"(.*?)\"";
      Pattern p = Pattern.compile(regex);
      Matcher lvMatcher = p.matcher(lvsErrMsg[1]);
      lvsTmp = null;
      if (lvMatcher.find()) {
        lvsTmp = lvMatcher.group(0);
      }
      lvFields=new String[]{lvsTmp};
    }
    lvsTmp=lvsErrMsg[2].replace("The error may involve ","");
    String lvsDaoStr=lvsTmp.replace(".update-Inline","").replace(".insert-Inline","")
            .replace(".delete-Inline","")
            .replace("\r","").replace("\n","");
    Class  lvClassz= null;
    Class lvcEntity=null;
    try {
      lvClassz = Class.forName(lvsDaoStr);
      while (lvClassz != Object.class) {
        Type[] t = lvClassz.getGenericInterfaces();
        if (t!=null&& t.length>0){
          if (t[0] instanceof ParameterizedType) {
            ParameterizedType lvPt= (ParameterizedType ) t[0];
            Type tt=lvPt.getActualTypeArguments()[0];
            lvcEntity=Class.forName(tt.getTypeName());
            break;
          }
        }
        lvClassz = lvClassz.getSuperclass();
      }
    } catch (ClassNotFoundException ex) {
      ex.printStackTrace();
    }
    if (lvcEntity==null) return e;
    Table lvTableAnno= (Table) lvcEntity.getAnnotation(Table.class);
    List<String> lvsFields=new ArrayList<>();
    lvsFields.addAll(Arrays.asList(lvFields));
    for (Column c:lvTableAnno.columns()){
      for (int i=0;i<lvsFields.size();i++){
        if (lvsFields.get(i).equals(c.name())){
          lvsFields.set(i,c.label());
        }
      }
    }
    String lvsNewMsg=pvsPrefix+(pvsPrefix.equals("")?"":": ")+"键值\"("+ Util.toString(lvsFields,",")+")"+(lvsValues.equals("")?"":"="+lvsValues);
    return new ModifyDataException(lvsNewMsg,lvFields);
  }
  //@ExceptionHandler(value = DuplicateKeyException.class)
  public Exception handleDataIntegrityViolationException(DataIntegrityViolationException e){
    ModifyDataException lvException= (ModifyDataException) convertException(
            e.getMessage().contains("非空约束")?"栏位不能为空":
            "记录被引用",e);
    String lvsMsg=lvException.getMessage().replace("是从表","被");
    if (!e.getMessage().contains("非空约束")) {
      String lvsPart[] = lvsMsg.split("\"");
      String lvsTableName = lvsPart[2];
      GenTable lvGenTable = genTableService.get(lvsTableName);
      lvsMsg=lvsPart[0]+lvsPart[1]+"\""+ lvGenTable.getComments()+"\""+lvsPart[3];
    }
    else{
      lvsMsg=lvsMsg.replace("键值","键");
    }
    return new ModifyDataException(lvsMsg,lvException.getRefDataFields()==null?null:
            lvException.getRefDataFields().toArray(new String[lvException.getRefDataFields().size()]));
  }
  public Exception handleDuplateKeyException(DuplicateKeyException e){
    ModifyDataException lvException= (ModifyDataException) convertException("重复输入",e);
    return lvException;
  }

}
